package com.summer.filesync.manager.service;

import com.summer.filesync.database.dao.FileMetadataDAO;
import com.summer.filesync.model.manager.BatchOperationResult;
import com.summer.filesync.util.Logger;
import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicInteger;

/** 文件操作服务 提供批量文件操作功能 */
public class FileOperationService {
  private static final Logger logger = Logger.getLogger(FileOperationService.class);

  private final FileMetadataDAO fileMetadataDAO;
  private final ExecutorService executorService;

  public FileOperationService(FileMetadataDAO fileMetadataDAO, ExecutorService executorService) {
    this.fileMetadataDAO = fileMetadataDAO;
    this.executorService = executorService;
  }

  /** 批量复制文件 */
  public CompletableFuture<BatchOperationResult> batchCopyFiles(
      List<String> sourcePaths, String destinationDirectory) {
    return CompletableFuture.supplyAsync(
        () -> {
          BatchOperationResult result = new BatchOperationResult("COPY");
          result.setTotalFiles(sourcePaths.size());

          AtomicInteger successCount = new AtomicInteger(0);
          AtomicInteger failureCount = new AtomicInteger(0);
          List<String> errors = new ArrayList<>();
          long totalSize = 0;

          try {
            // 确保目标目录存在
            Path destDir = Paths.get(destinationDirectory);
            if (!Files.exists(destDir)) {
              Files.createDirectories(destDir);
            }

            for (String sourcePath : sourcePaths) {
              try {
                Path source = Paths.get(sourcePath);
                if (!Files.exists(source)) {
                  errors.add("源文件不存在: " + sourcePath);
                  failureCount.incrementAndGet();
                  continue;
                }

                String fileName = source.getFileName().toString();
                Path destination = destDir.resolve(fileName);

                // 处理文件名冲突
                destination = resolveNameConflict(destination);

                // 复制文件
                if (Files.isDirectory(source)) {
                  copyDirectoryRecursively(source, destination);
                } else {
                  Files.copy(source, destination, StandardCopyOption.REPLACE_EXISTING);
                  totalSize += Files.size(source);
                }

                successCount.incrementAndGet();
                logger.debug("成功复制文件: " + sourcePath + " -> " + destination);

              } catch (Exception e) {
                failureCount.incrementAndGet();
                errors.add("复制失败 " + sourcePath + ": " + e.getMessage());
                logger.error("复制文件失败: " + sourcePath, e);
              }
            }

            result.setSuccessCount(successCount.get());
            result.setFailureCount(failureCount.get());
            result.setErrors(errors);
            result.setTotalSizeBytes(totalSize);
            result.setSuccess(failureCount.get() == 0);

          } catch (Exception e) {
            result.setSuccess(false);
            errors.add("批量复制操作失败: " + e.getMessage());
            result.setErrors(errors);
            logger.error("批量复制操作失败", e);
          }

          result.complete();
          return result;
        },
        executorService);
  }

  /** 批量移动文件 */
  public CompletableFuture<BatchOperationResult> batchMoveFiles(
      List<String> sourcePaths, String destinationDirectory) {
    return CompletableFuture.supplyAsync(
        () -> {
          BatchOperationResult result = new BatchOperationResult("MOVE");
          result.setTotalFiles(sourcePaths.size());

          AtomicInteger successCount = new AtomicInteger(0);
          AtomicInteger failureCount = new AtomicInteger(0);
          List<String> errors = new ArrayList<>();
          long totalSize = 0;

          try {
            Path destDir = Paths.get(destinationDirectory);
            if (!Files.exists(destDir)) {
              Files.createDirectories(destDir);
            }

            for (String sourcePath : sourcePaths) {
              try {
                Path source = Paths.get(sourcePath);
                if (!Files.exists(source)) {
                  errors.add("源文件不存在: " + sourcePath);
                  failureCount.incrementAndGet();
                  continue;
                }

                String fileName = source.getFileName().toString();
                Path destination = destDir.resolve(fileName);
                destination = resolveNameConflict(destination);

                if (!Files.isDirectory(source)) {
                  totalSize += Files.size(source);
                }

                Files.move(source, destination, StandardCopyOption.REPLACE_EXISTING);

                successCount.incrementAndGet();
                logger.debug("成功移动文件: " + sourcePath + " -> " + destination);

              } catch (Exception e) {
                failureCount.incrementAndGet();
                errors.add("移动失败 " + sourcePath + ": " + e.getMessage());
                logger.error("移动文件失败: " + sourcePath, e);
              }
            }

            result.setSuccessCount(successCount.get());
            result.setFailureCount(failureCount.get());
            result.setErrors(errors);
            result.setTotalSizeBytes(totalSize);
            result.setSuccess(failureCount.get() == 0);

          } catch (Exception e) {
            result.setSuccess(false);
            errors.add("批量移动操作失败: " + e.getMessage());
            result.setErrors(errors);
            logger.error("批量移动操作失败", e);
          }

          result.complete();
          return result;
        },
        executorService);
  }

  /** 批量删除文件 */
  public CompletableFuture<BatchOperationResult> batchDeleteFiles(List<String> filePaths) {
    return CompletableFuture.supplyAsync(
        () -> {
          BatchOperationResult result = new BatchOperationResult("DELETE");
          result.setTotalFiles(filePaths.size());

          AtomicInteger successCount = new AtomicInteger(0);
          AtomicInteger failureCount = new AtomicInteger(0);
          List<String> errors = new ArrayList<>();
          long totalSize = 0;

          for (String filePath : filePaths) {
            try {
              Path path = Paths.get(filePath);
              if (!Files.exists(path)) {
                errors.add("文件不存在: " + filePath);
                failureCount.incrementAndGet();
                continue;
              }

              if (!Files.isDirectory(path)) {
                totalSize += Files.size(path);
              }

              if (Files.isDirectory(path)) {
                deleteDirectoryRecursively(path);
              } else {
                Files.delete(path);
              }

              successCount.incrementAndGet();
              logger.debug("成功删除文件: " + filePath);

            } catch (Exception e) {
              failureCount.incrementAndGet();
              errors.add("删除失败 " + filePath + ": " + e.getMessage());
              logger.error("删除文件失败: " + filePath, e);
            }
          }

          result.setSuccessCount(successCount.get());
          result.setFailureCount(failureCount.get());
          result.setErrors(errors);
          result.setTotalSizeBytes(totalSize);
          result.setSuccess(failureCount.get() == 0);
          result.complete();

          return result;
        },
        executorService);
  }

  /** 批量重命名文件 */
  public CompletableFuture<BatchOperationResult> batchRenameFiles(Map<String, String> renameMap) {
    return CompletableFuture.supplyAsync(
        () -> {
          BatchOperationResult result = new BatchOperationResult("RENAME");
          result.setTotalFiles(renameMap.size());

          AtomicInteger successCount = new AtomicInteger(0);
          AtomicInteger failureCount = new AtomicInteger(0);
          List<String> errors = new ArrayList<>();

          for (Map.Entry<String, String> entry : renameMap.entrySet()) {
            String oldPath = entry.getKey();
            String newName = entry.getValue();

            try {
              Path oldFile = Paths.get(oldPath);
              if (!Files.exists(oldFile)) {
                errors.add("源文件不存在: " + oldPath);
                failureCount.incrementAndGet();
                continue;
              }

              Path parent = oldFile.getParent();
              Path newFile = parent.resolve(newName);

              if (Files.exists(newFile)) {
                errors.add("目标文件已存在: " + newFile);
                failureCount.incrementAndGet();
                continue;
              }

              Files.move(oldFile, newFile);
              successCount.incrementAndGet();
              logger.debug("成功重命名文件: " + oldPath + " -> " + newFile);

            } catch (Exception e) {
              failureCount.incrementAndGet();
              errors.add("重命名失败 " + oldPath + ": " + e.getMessage());
              logger.error("重命名文件失败: " + oldPath, e);
            }
          }

          result.setSuccessCount(successCount.get());
          result.setFailureCount(failureCount.get());
          result.setErrors(errors);
          result.setSuccess(failureCount.get() == 0);
          result.complete();

          return result;
        },
        executorService);
  }

  /** 清理临时文件 */
  public int cleanupTempFiles() {
    int deletedCount = 0;

    try {
      String tempDir = System.getProperty("java.io.tmpdir");
      Path tempPath = Paths.get(tempDir);

      Files.walk(tempPath)
          .filter(Files::isRegularFile)
          .filter(this::isTempFile)
          .forEach(
              path -> {
                try {
                  Files.delete(path);
                  logger.debug("删除临时文件: " + path);
                } catch (IOException e) {
                  logger.warn("无法删除临时文件: " + path, e);
                }
              });

    } catch (Exception e) {
      logger.error("清理临时文件失败", e);
    }

    return deletedCount;
  }

  /** 解决文件名冲突 */
  private Path resolveNameConflict(Path destination) {
    if (!Files.exists(destination)) {
      return destination;
    }

    String fileName = destination.getFileName().toString();
    String nameWithoutExt;
    String extension;

    int dotIndex = fileName.lastIndexOf('.');
    if (dotIndex > 0) {
      nameWithoutExt = fileName.substring(0, dotIndex);
      extension = fileName.substring(dotIndex);
    } else {
      nameWithoutExt = fileName;
      extension = "";
    }

    int counter = 1;
    Path newDestination;
    do {
      String newFileName = nameWithoutExt + "_" + counter + extension;
      newDestination = destination.getParent().resolve(newFileName);
      counter++;
    } while (Files.exists(newDestination));

    return newDestination;
  }

  /** 递归复制目录 */
  private void copyDirectoryRecursively(Path source, Path destination) throws IOException {
    Files.walk(source)
        .forEach(
            sourcePath -> {
              try {
                Path destPath = destination.resolve(source.relativize(sourcePath));
                if (Files.isDirectory(sourcePath)) {
                  Files.createDirectories(destPath);
                } else {
                  Files.copy(sourcePath, destPath, StandardCopyOption.REPLACE_EXISTING);
                }
              } catch (IOException e) {
                logger.error("复制失败: " + sourcePath, e);
              }
            });
  }

  /** 递归删除目录 */
  private void deleteDirectoryRecursively(Path directory) throws IOException {
    Files.walk(directory).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
  }

  /** 判断是否为临时文件 */
  private boolean isTempFile(Path path) {
    String fileName = path.getFileName().toString().toLowerCase();
    return fileName.startsWith("tmp")
        || fileName.endsWith(".tmp")
        || fileName.endsWith(".temp")
        || fileName.startsWith("~");
  }
}
